
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;



public class Math {

	public HashMap<String,Integer> argFctPredefinie = new HashMap<String,Integer>();
	
	public HashMap<String,Method> methodFctPredefinie = new HashMap<String,Method>();
	
	
	public Math(){
		argFctPredefinie.put("somme", 2);
		argFctPredefinie.put("produit", 2);
		argFctPredefinie.put("division", 2);
		argFctPredefinie.put("soustraction", 2);
		argFctPredefinie.put("moins", 1);
		argFctPredefinie.put("modulo", 2);
		argFctPredefinie.put("cos", 1);
		argFctPredefinie.put("sin", 1);
		argFctPredefinie.put("tan", 1);
		argFctPredefinie.put("arccos", 1);
		argFctPredefinie.put("arcsin", 1);
		argFctPredefinie.put("arctan", 1);
		argFctPredefinie.put("arrondie", 1);
		argFctPredefinie.put("abs", 1);
		argFctPredefinie.put("signe", 1);
		argFctPredefinie.put("puissance", 2);
		argFctPredefinie.put("racine", 1);
		argFctPredefinie.put("exp", 1);
		argFctPredefinie.put("ln", 1);
		argFctPredefinie.put("log10", 1);
		argFctPredefinie.put("pi", 0);
		argFctPredefinie.put("hasard", 1);		
		
		
		Class c = Math.class;
		Method[] tab = c.getMethods();
		
		Method  m;
		for (int i=0;i<tab.length;i++) {
			m = tab[i];
			if(m.getName().equals("somme"))
				methodFctPredefinie.put("somme", m);			
			if(m.getName().equals("produit"))
				methodFctPredefinie.put("produit", m);			
			if(m.getName().equals("division"))
				methodFctPredefinie.put("division", m);			
			if(m.getName().equals("soustraction"))
				methodFctPredefinie.put("soustraction", m);			
			if(m.getName().equals("moins"))
				methodFctPredefinie.put("moins", m);			
			if(m.getName().equals("modulo"))
				methodFctPredefinie.put("modulo", m);			
			if(m.getName().equals("cos"))
				methodFctPredefinie.put("cos", m);			
			if(m.getName().equals("sin"))
				methodFctPredefinie.put("sin", m);			
			if(m.getName().equals("tan"))
				methodFctPredefinie.put("tan", m);			
			if(m.getName().equals("arccos"))
				methodFctPredefinie.put("arccos", m);			
			if(m.getName().equals("arcsin"))
				methodFctPredefinie.put("arcsin", m);			
			if(m.getName().equals("arctan"))
				methodFctPredefinie.put("arctan", m);			
			if(m.getName().equals("arrondie"))
				methodFctPredefinie.put("arrondie", m);			
			if(m.getName().equals("signe"))
				methodFctPredefinie.put("signe", m);			
			if(m.getName().equals("abs"))
				methodFctPredefinie.put("abs", m);			
			if(m.getName().equals("puissance"))
				methodFctPredefinie.put("puissance", m);			
			if(m.getName().equals("racine"))
				methodFctPredefinie.put("racine", m);			
			if(m.getName().equals("exp"))
				methodFctPredefinie.put("exp", m);			
			if(m.getName().equals("ln"))
				methodFctPredefinie.put("ln", m);			
			if(m.getName().equals("log10"))
				methodFctPredefinie.put("log10", m);			
			if(m.getName().equals("pi"))
				methodFctPredefinie.put("pi", m);
			if(m.getName().equals("hasard"))
				methodFctPredefinie.put("hasard", m);
		}    
	};
	
	
	
	public static Object somme(ArrayList<Object> v, HashMap<String, Object> penv)
	{	
		double sum = 0;
		boolean t= true;
		int n = 0;

		while(t && n<v.size()) {
			t = false;
			if (v.get(n) instanceof Double ) {
				t = true;
				sum = sum + (Double)v.get(n);
			}
			if(v.get(n) instanceof Integer) {
				t = true;
				sum = sum + (Integer)v.get(n);
			}	
		n++;	
		}			
		
		if(t)
			if(sum%1 == 0)
				return (int)sum;
			else
				return sum;
		else
			return null;
	}
	
	public static Object soustraction(ArrayList<Object> v, HashMap<String, Object> penv)
	{	
		double sum = 0;
		boolean t = false;
		int n = 1;
		
		if (v.get(0) instanceof Double) {
			sum = (Double)v.get(0);
			t = true;
		}
		if (v.get(0) instanceof Integer) {
			sum = (Integer)v.get(0);
			t = true;
		}
		
		while(t && n<v.size()) {
			t = false;
			if (v.get(n) instanceof Double ) {
				t = true;
				sum = sum - (Double)v.get(n);
			}
			if(v.get(n) instanceof Integer) {
				t = true;
				sum = sum - (Integer)v.get(n);
			}	
		n++;	
		}			
		
		if(t)
			if(sum%1 == 0)
				return (int)sum;
			else
				return sum;
		else
			return null;
	}
	
	
	public static Object produit(ArrayList<Object> v, HashMap<String, Object> penv)
	{	
		double sum = 1;
		boolean t= true;
		int n = 0;
		
		while(t && n<v.size()) {
			t = false;
			if (v.get(n) instanceof Double ) {
				t = true;
				sum = sum * (Double)v.get(n);
			}
			if(v.get(n) instanceof Integer) {
				t = true;
				sum = sum * (Integer)v.get(n);
			}	
		n++;	
		}			
		
		if(t)
			if(sum % 1 == 0)
				return (int)sum;
			else
				return sum;
		else
			return null;
	}
	
	public static Object division(ArrayList<Object> v, HashMap<String, Object> penv)
	{	
		double sum = 1;
		boolean t= true;
		int n = 1;
		
		if (v.get(0) instanceof Double) {
			sum = (Double)v.get(0);
			t = true;
		}
		if (v.get(0) instanceof Integer) {
			sum = (Integer)v.get(0);
			t = true;
		}
		
		while(t && n<v.size()) {
			t = false;
			if (v.get(n) instanceof Double ) {
				t = true;
				sum = sum / (Double)v.get(n);
			}
			if(v.get(n) instanceof Integer) {
				t = true;
				sum = sum / (Integer)v.get(n);
			}	
		n++;	
		}			
		
		if(t)
			if(sum%1 == 0)
				return (int)sum;
			else
				return sum;
		else
			return null;
	}

	
	public static Object moins(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if (v.size() == 1) {
			if(v.get(0) instanceof Integer)
				return 0 - (Integer)v.get(0);
			if( v.get(0) instanceof Double)
				return 0.0 - (Double)v.get(0);
		}
		return null;		
	}
	
	
	public static Object modulo(ArrayList<Object> v, HashMap<String, Object> penv) {
	
		if (v.size() == 2 && v.get(0) instanceof Integer && v.get(1) instanceof Integer) {
			return (Integer)v.get(0) % (Integer)v.get(1);
		}
		
		return null;		
	}
		
	
	public static Object cos(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.cos(java.lang.Math.toRadians((Double)v.get(0)));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.cos(java.lang.Math.toRadians((double)(Integer)v.get(0)));
			else 
				return null;
		}
		return null;		
	}
	
	
	public static Object sin(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.sin(java.lang.Math.toRadians((Double)v.get(0)));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.sin(java.lang.Math.toRadians((double)(Integer)v.get(0)));
			else 
				return null;
		}
		return null;		
	}
	
	
	public static Object tan(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.tan(java.lang.Math.toRadians((Double)v.get(0)));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.tan(java.lang.Math.toRadians((double)(Integer)v.get(0)));
			else 
				return null;
		}
		return null;		
	}
	
	
public static Object arccos(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.acos(java.lang.Math.toRadians((Double)v.get(0)));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.acos(java.lang.Math.toRadians((double)(Integer)v.get(0)));
			else 
				return null;
		}
		return null;		
	}
	
	
	public static Object arcsin(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.asin(java.lang.Math.toRadians((Double)v.get(0)));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.asin(java.lang.Math.toRadians((double)(Integer)v.get(0)));
			else 
				return null;
		}
		return null;		
	}
	
	
	public static Object arctan(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.atan(java.lang.Math.toRadians((Double)v.get(0)));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.atan(java.lang.Math.toRadians((double)(Integer)v.get(0)));
			else 
				return null;
		}
		return null;		
	}
	
	
	public static Object arrondie(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return (int)java.lang.Math.round((Double)v.get(0));
			if(v.get(0) instanceof Integer)
				return (Integer)v.get(0);
			else 
				return null;
		}
		return null;		
	}
	

	public static Object abs(ArrayList<Object> v, HashMap<String, Object> penv) {

		if (v.size() == 1 && v.get(0) instanceof Integer){
			return java.lang.Math.abs((Integer)v.get(0));
		}
		return null;		
	}
	
	
	public static Object signe(ArrayList<Object> v, HashMap<String, Object> penv) {
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return (int)java.lang.Math.round(java.lang.Math.signum((Double)v.get(0)));
			if(v.get(0) instanceof Integer)
				return (int)java.lang.Math.round(java.lang.Math.signum((double)(Integer)v.get(0)));
			else 
				return null;
		}
		return null;		
	}
	
	
	public static Object puissance(ArrayList<Object> v, HashMap<String, Object> penv) {
		if (v.size() == 2){
			if(v.get(0) instanceof Double && v.get(1) instanceof Double)
				return java.lang.Math.pow((Double)v.get(0), (Double)v.get(1));
			
			if(v.get(0) instanceof Double && v.get(1) instanceof Integer)
				return java.lang.Math.pow((Double)v.get(0), (double)(Integer)v.get(1));
			
			if(v.get(0) instanceof Integer && v.get(1) instanceof Double)
				return java.lang.Math.pow((double)(Integer)v.get(0), (Double)v.get(1));
			
			if(v.get(0) instanceof Integer && v.get(1) instanceof Integer)
				return java.lang.Math.pow((double)(Integer)v.get(0), (double)(Integer)v.get(1));
			
			else 
				return null;
		}
		return null;		
	}
	
		public static Object racine(ArrayList<Object> v, HashMap<String, Object> penv) {
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.sqrt((Double)v.get(0));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.sqrt((double)(Integer)v.get(0));
			else 
				return null;
		}
		return null;		
	}
		
	
	public static Object exp(ArrayList<Object> v, HashMap<String, Object> penv) {
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.exp((Double)v.get(0));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.exp((double)(Integer)v.get(0));
			else 
				return null;
		}
		return null;		
	}
	
	public static Object ln(ArrayList<Object> v, HashMap<String, Object> penv) {
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.log((Double)v.get(0));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.log((double)(Integer)v.get(0));
			else 
				return null;
		}
		return null;		
	}
	
	
	public static Object log10(ArrayList<Object> v, HashMap<String, Object> penv) {
		if (v.size() == 1){
			if(v.get(0) instanceof Double)
				return java.lang.Math.log10((Double)v.get(0));
			if(v.get(0) instanceof Integer)
				return java.lang.Math.log10((double)(Integer)v.get(0));
			else 
				return null;
		}
		return null;		
	}
	
	
	public static Object pi(ArrayList<Object> v, HashMap<String, Object> penv) {
		if (v.size() == 0){
			return java.lang.Math.PI;
		}
		return null;		
	}
	
	public static Object hasard(ArrayList<Object> v, HashMap<String, Object> penv) {
		
		if(v.size() == 1 && v.get(0) instanceof Integer)
			return (int)java.lang.Math.round(java.lang.Math.random()*(Integer)v.get(0));	
		else
			return null;
	
	}
	
}
